﻿using MongoDB.Driver;
using Moq;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Companies;
using Sustainalytics.DataLayer.EsgRatings;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.MongoDB.Extensions;
using Sustainalytics.Portfolios.BL.Exceptions;
using Sustainalytics.Portfolios.BL.Model;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Configuration.Abstractions;
using System.Linq;
using System.Linq.Expressions;
using Xunit;

namespace Sustainalytics.Portfolios.BL.Tests.UnitTest
{
    [Trait("Category", "Unit")]
    public class PortfolioManagerTests
    {
        public class PortfolioSecuritiesGet
        {
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly IPortfolioReadHandler _sut;
            private readonly Mock<IRepositoryCollection<CorporateDataBasic>> _universesRepositoryMock;

            private readonly Guid _portfolioId = new Guid("4387c2a7-0000-0000-0000-6c3be5be9f98");

            private readonly PortfolioUserClaims _user;
            private readonly Guid[] _companyIds;
            private readonly IList<PortfolioDetails> _portfolioSecurities;

            public PortfolioSecuritiesGet()
            {
                _user = new PortfolioUserClaims
                {
                    UserName = "ileana.popescu@sustainalytics.com",
                    UserFullName = "Ileana Popescu",
                    UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                    AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
                };
                _companyIds = new Guid[] {
                    new Guid("00000000-0000-0000-0000-000000000001"),
                    new Guid("00000000-0000-0000-0000-000000000002")
                };

                _portfolioSecurities = new List<PortfolioDetails>()
                {
                    new PortfolioDetails
                    {
                        CompanyId = _companyIds[0],
                        PortfolioId = _portfolioId,
                        DisplayInfo = new DisplayInformation("123", "security"),
                        MatchedInfo = new MatchedInformation("123", "testCompany"),
                        SecurityId = "1",
                        Id =  new Guid("00000000-0000-0000-0000-000000000004")
                    },
                    new PortfolioDetails
                    {
                        CompanyId =_companyIds[1],
                        PortfolioId = _portfolioId,
                        DisplayInfo = new DisplayInformation("123", "security"),
                        MatchedInfo = new MatchedInformation("123", "testCompany"),
                        SecurityId = "2",
                        Id =  new Guid("00000000-0000-0000-0000-000000000005")
                    }
                };
                var portfolio = PortfolioBuilder.Build(_portfolioId, "test", PortfolioSharingStatus.Private,
                    _user);

                var portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                portfolioRepositoryMock.Setup(x => x.Read(It.Is<Guid>(p => p == _portfolioId)))
                    .Returns(portfolio);

                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();
                _universesRepositoryMock = new Mock<IRepositoryCollection<CorporateDataBasic>>();

                _sut = new PortfolioReadHandler(
                   new PortfolioTypeCollection<Portfolio>(portfolioRepositoryMock.Object, new Mock<IRepositoryCollection<Portfolio>>().Object),
                   new PortfolioTypeCollection<PortfolioDetails>(_portfolioDetailsRepositoryMock.Object, new Mock<IRepositoryCollection<PortfolioDetails>>().Object),
                   _universesRepositoryMock.Object);

            }

            [Fact]
            public void When_all_accessible_Retuns_All_Accessible_securities()
            {
                var corporateDataBasic = new[]
                {
                    new CorporateDataBasic(){Id = _companyIds[0],UniverseIds = new List<int>{1,2,3,4}},
                    new CorporateDataBasic(){Id = _companyIds[1],UniverseIds = new List<int>{1,2,3,4}}
                };

                _user.AddAccountUniverses(new[] { 1, 2 });

                _portfolioDetailsRepositoryMock.Setup(
                repo => repo.ReadWhere(
                    It.IsAny<Expression<Func<PortfolioDetails, bool>>>()
                    , It.IsAny<int?>()
                    , It.IsAny<int?>()
                    , It.IsAny<Ordering<PortfolioDetails>>()
                    , It.IsAny<Expression<Func<PortfolioDetails, object>>[]>()
                    ))
                .Returns(
                (Expression<Func<PortfolioDetails, bool>> d, int? t, int? k, Ordering<PortfolioDetails> o, Expression<Func<PortfolioDetails, object>>[] s)
                    => _portfolioSecurities.Where(d.Compile()).ToList());
                _universesRepositoryMock.Setup(repo => repo.ReadWhere(
                    It.IsAny<Expression<Func<CorporateDataBasic, bool>>>()
                    , It.IsAny<int?>()
                    , It.IsAny<int?>()
                    , It.IsAny<Ordering<CorporateDataBasic>>()
                    , It.IsAny<Expression<Func<CorporateDataBasic, object>>[]>()
                    ))
                    .Returns(corporateDataBasic);

                var actual = _sut.GetPortfolioSecurities(_portfolioId, _user).Select(x => x.Id).ToList();
                var expected =
                    _portfolioSecurities.Select(
                        x =>
                            new PortfolioSecurityModel(x.Id, x.PortfolioId, x.DisplayInfo, x.MatchedInfo, x.CompanyId, x.CompanyNameUrlFriendly, x.SecurityId, 
                                 x.SecurityWeight)).Select(x => x.Id).ToList();

                Assert.Equal(expected, actual);
            }

            [Fact]
            public void When_some_Inaccesible_Retuns_Marked_as_Inaaccesible_securities()
            {
                var corporateDataBasic = new[]
                {
                    new CorporateDataBasic(){Id = _companyIds[0],UniverseIds = new List<int>{1,2}},
                    new CorporateDataBasic(){Id = _companyIds[1],UniverseIds = new List<int>{1,2,3,4}}
                };

                _user.AddAccountUniverses(new[] { 3, 4 });

                _portfolioDetailsRepositoryMock.Setup(
                repo => repo.ReadWhere(
                    It.IsAny<Expression<Func<PortfolioDetails, bool>>>()
                    , It.IsAny<int?>()
                    , It.IsAny<int?>()
                    , It.IsAny<Ordering<PortfolioDetails>>()
                    , It.IsAny<Expression<Func<PortfolioDetails, object>>[]>()
                    ))
                .Returns(_portfolioSecurities);
                _universesRepositoryMock.Setup(repo => repo.ReadWhere(
                    It.IsAny<Expression<Func<CorporateDataBasic, bool>>>()
                    , It.IsAny<int?>()
                    , It.IsAny<int?>()
                    , It.IsAny<Ordering<CorporateDataBasic>>()
                    , It.IsAny<Expression<Func<CorporateDataBasic, object>>[]>()
                    ))
                    .Returns(corporateDataBasic);

                var actual = _sut.GetPortfolioSecurities(_portfolioId, _user).Select(x => new KeyValuePair<Guid, bool>(x.CompanyId, x.IsAccesible));
                var expected =
                    corporateDataBasic.Select(
                        x =>
                            new KeyValuePair<Guid, bool>
                            (
                                x.Id
                                , !x.UniverseIds.IsNullOrEmpty() && !x.UniverseIds.Intersect(_user.Universes).IsNullOrEmpty()
                            ));

                Assert.Equal(expected, actual);
            }
        }


        public class PortfolioSecuritiesDelete
        {
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioMatches>> _portfolioMatchesRepositoryMock;
            private readonly ICustomPortfolioUpdateHandler _sut;
            private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioUserInput>> _userInputRepositoryMock = new Mock<IRepositoryCollection<PortfolioUserInput>>();
            private readonly Mock<IScreeningToolFilterManager> _filterMock = new Mock<IScreeningToolFilterManager>();
            private readonly Mock<ISubscribeToPortfolioManagement> _subscriptionManagement = new Mock<ISubscribeToPortfolioManagement>();
            private readonly Mock<IEsgInputFileRepository> _esgInputFileRepositoryMock;


            private readonly PortfolioUserClaims _userClaimsFake = new PortfolioUserClaims
            {
                UserName = "ileana.popescu@sustainalytics.com",
                UserFullName = "Ileana Popescu",
                UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            private readonly Dictionary<string, string> _serviceBusParams = new Dictionary<string, string>
            {
                { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
                { "RegionEndpoint", "TT" },
                { "SessionId", "Portfolios" },
                { "TopicPath", "test-topic" },
            };

            public PortfolioSecuritiesDelete()
            {
                _portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();
                _esgInputFileRepositoryMock = new Mock<IEsgInputFileRepository>();
                _sut = new CustomPortfolioUpdateHandler(_portfolioRepositoryMock.Object,
                    _portfolioDetailsRepositoryMock.Object,
                    _portfolioMatchesRepositoryMock.Object,
                    _userInputRepositoryMock.Object,
                    _esgInputFileRepositoryMock.Object, new Replication.Publisher.ServiceBusPublisher( _serviceBusParams),
                    new CompanyMatchingLogic(MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                _sut.SetScreeningToolFilterManagement(_filterMock.Object);
                _sut.SetSubscriptionManager(_subscriptionManagement.Object);
            }

            [Fact]
            public void DeletePortfolioSecurity_DeleteSecurity_Portfolio_CompanyCount_Is_Decresed_By_1()
            {
                //Arrange
                var _portfolioGuid = Guid.NewGuid();
                var _securityId = Guid.NewGuid();
                Portfolio updatedPortfolio = null;

                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Private, _userClaimsFake);
                portfolio.CompanyCount = 2;
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);
                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);

                //Act
                _sut.DeletePortfolioSecurity(_portfolioGuid, _securityId, _userClaimsFake);

                //Assert
                Assert.Equal(1, updatedPortfolio.CompanyCount);
            }

            [Fact]
            public void DeletePortfolioSecurity_DeleteSecurity_Portfolio_PortfolioModified_Date_Is_Set_With_Today()
            {
                //Arrange
                var _portfolioGuid = Guid.NewGuid();
                var _securityId = Guid.NewGuid();
                Portfolio updatedPortfolio = null;

                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Private, _userClaimsFake);
                portfolio.DateModified = DateTime.Today.AddDays(-1);
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);
                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);

                //Act
                _sut.DeletePortfolioSecurity(_portfolioGuid, _securityId, _userClaimsFake);

                //Assert
                Assert.Equal(DateTime.Today, updatedPortfolio.DateModified);
            }
        }

        public class PortfolioIntegrationWithAletsTests
        {
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly IPortfolioReadHandler _sut;
            private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock;

            public PortfolioIntegrationWithAletsTests()
            {
                _portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();

                var _universesRepositoryMock = new Mock<IRepositoryCollection<CorporateDataBasic>>();

                _sut = new PortfolioReadHandler(
                    new PortfolioTypeCollection<Portfolio>(_portfolioRepositoryMock.Object, new Mock<IRepositoryCollection<Portfolio>>().Object),
                    new PortfolioTypeCollection<PortfolioDetails>(_portfolioDetailsRepositoryMock.Object, new Mock<IRepositoryCollection<PortfolioDetails>>().Object),
                    _universesRepositoryMock.Object);
            }

            [Fact]
            public void GetCompanyIdsByPortfolio_Should_Return_All_Distinct_Companies_In_Same_Portfolio()
            {
                var portfolioId = Guid.NewGuid();
                var portfolioSecurities = new List<PortfolioDetails>()
                {
                    new PortfolioDetails{CompanyId = Guid.NewGuid(), PortfolioId = portfolioId},
                    new PortfolioDetails{CompanyId = Guid.NewGuid(), PortfolioId = portfolioId},
                    new PortfolioDetails{CompanyId = Guid.NewGuid(), PortfolioId = portfolioId},
                    new PortfolioDetails{CompanyId = Guid.NewGuid(), PortfolioId = portfolioId},
                };

                _portfolioDetailsRepositoryMock.Setup(
                    repo => repo.ReadWhere(It.IsAny<Expression<Func<PortfolioDetails, bool>>>(), It.IsAny<int?>(), It.IsAny<int?>(), It.IsAny<Ordering<PortfolioDetails>>(), It.IsAny<Expression<Func<PortfolioDetails, object>>[]>()))
                    .Returns((Expression<Func<PortfolioDetails, bool>> d, int? t, int? k, Ordering<PortfolioDetails> o, Expression<Func<PortfolioDetails, object>>[] s) => portfolioSecurities.Where(d.Compile()).ToList());

                //act
                var result = _sut.GetCompanyIdsByPortfolio(portfolioId);

                Assert.Equal(portfolioSecurities.Select(x => x.CompanyId).Distinct().Dump(), result.Dump());
            }

            [Fact]
            public void GetPortfoliosByCompanyId_Should_Return_All_Portfolios()
            {
                var portfolioIds = new[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
                var companyId = Guid.NewGuid();
                var portfolioSecurities = new List<PortfolioDetails>
                {
                    new PortfolioDetails{CompanyId = companyId, PortfolioId = portfolioIds[0]},
                    new PortfolioDetails{CompanyId = companyId, PortfolioId = portfolioIds[0]},
                    new PortfolioDetails{CompanyId = companyId, PortfolioId = portfolioIds[1]},
                    new PortfolioDetails{CompanyId = Guid.NewGuid(), PortfolioId = portfolioIds[0]},
                };

                var portfolios = new[]
                {
                    new Portfolio() {Id = portfolioIds[0]},
                    new Portfolio() {Id = portfolioIds[1]}
                };

                _portfolioDetailsRepositoryMock.Setup(
                    repo => repo.ReadWhere(It.IsAny<Expression<Func<PortfolioDetails, bool>>>(), It.IsAny<int?>(), It.IsAny<int?>(), It.IsAny<Ordering<PortfolioDetails>>(), It.IsAny<Expression<Func<PortfolioDetails, object>>[]>()))
                    .Returns((Expression<Func<PortfolioDetails, bool>> d, int? t, int? k, Ordering<PortfolioDetails> o, Expression<Func<PortfolioDetails, object>>[] s) => portfolioSecurities.Where(d.Compile()).ToList());

                _portfolioRepositoryMock.Setup(repo => repo.ReadWhere(It.IsAny<Expression<Func<Portfolio, bool>>>(), It.IsAny<int?>(), It.IsAny<int?>(), It.IsAny<Ordering<Portfolio>>(), It.IsAny<Expression<Func<Portfolio, object>>[]>()))
                    .Returns(
                        (Expression<Func<Portfolio, bool>> e, int? t, int? k, Ordering<Portfolio> o, Expression<Func<Portfolio, object>>[] s) => portfolios.Where(e.Compile()).ToList());

                //act
                var result = _sut.GetPortfoliosByCompanyId(companyId);

                var expectedResult = portfolios.Where(portfolio => portfolioSecurities.Where(x => x.CompanyId == companyId).Select(x => x.PortfolioId).Distinct().Contains(portfolio.Id));

                Assert.Equal(expectedResult.Dump(), result.Dump());
            }
        }

        public class PortfolioUpdateTest
        {
            private readonly ICustomPortfolioUpdateHandler _sut;
            private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioMatches>> _portfolioMatchesRepositoryMock;
            private readonly Mock<IEsgInputFileRepository> _esgInputFileRepositoryMock;



            private readonly Mock<IRepositoryCollection<PortfolioUserInput>> _userInputRepositoryMock;
            private readonly Mock<IScreeningToolFilterManager> _filterMock;
            private readonly Mock<ISubscribeToPortfolioManagement> _subscriptionManagement;
            private readonly Guid _portfolioGuid;
            private readonly PortfolioUserClaims _user;
            private readonly PortfolioUserClaims _anotherUser;
            private readonly Dictionary<string, string> _serviceBusParams = new Dictionary<string, string>
            {
                { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
                { "RegionEndpoint", "TT" },
                { "SessionId", "Portfolios" },
                { "TopicPath", "test-topic" },
            };

            public PortfolioUpdateTest()
            {
                _portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();
                _portfolioMatchesRepositoryMock = new Mock<IRepositoryCollection<PortfolioMatches>>();
                _esgInputFileRepositoryMock = new Mock<IEsgInputFileRepository>();
                _userInputRepositoryMock = new Mock<IRepositoryCollection<PortfolioUserInput>>();
                _filterMock = new Mock<IScreeningToolFilterManager>();
                _subscriptionManagement = new Mock<ISubscribeToPortfolioManagement>();
                _sut = new CustomPortfolioUpdateHandler(_portfolioRepositoryMock.Object, _portfolioDetailsRepositoryMock.Object,
                    _portfolioMatchesRepositoryMock.Object,
                    _userInputRepositoryMock.Object,
                    _esgInputFileRepositoryMock.Object , new Replication.Publisher.ServiceBusPublisher(_serviceBusParams),
                    new CompanyMatchingLogic(MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                _sut.SetScreeningToolFilterManagement(_filterMock.Object);
                _sut.SetSubscriptionManager(_subscriptionManagement.Object);
                _portfolioGuid = Guid.NewGuid();
                _user = new PortfolioUserClaims
                {
                    UserName = "ileana.popescu@sustainalytics.com",
                    UserFullName = "Ileana Popescu",
                    UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                    AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
                };

                _anotherUser = new PortfolioUserClaims
                {
                    UserName = "teodor.bajan@sustainalytics.com",
                    UserFullName = "Teodor bajan",
                    UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f99"),
                    AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
                };
            }

            [Fact]
            public void Portfolio_Update_Status_ThrowsException_When_Modification_Unauthorized()
            {
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared,
                   _user);

                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                //Assert
                Assert.Throws<PortfolioModificationUnauthorizedException>(() => _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Private, _anotherUser));
            }

            [Fact]
            public void Portfolio_Update_Status_Portfolio_From_Private_To_Shared_Status_Gets_Changed()
            {
                //Arrange
                Portfolio updatedPortfolio = null;

                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Private, _user);
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);
                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);

                //Act
                _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Shared, _user);

                //Assert
                Assert.Equal(PortfolioSharingStatus.Shared, updatedPortfolio.SharingStatus);
            }

            [Fact]
            public void Portfolio_Update_Status_Date_Modified_Gets_Changed()
            {
                //Arrange
                Portfolio updatedPortfolio = null;

                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Private, _user);
                portfolio.DateModified = DateTime.Today.AddDays(-2);
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);
                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);

                //Act
                _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Shared, _user);

                //Assert
                Assert.Equal(DateTime.Today, updatedPortfolio.DateModified);
            }

            [Fact]
            public void PortfolioUpdate_Status_To_Private_Updates_Subscriptions()
            {
                //arrange
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared, _user);
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                //Act
                _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Private, _user);

                //Assert
                _subscriptionManagement.Verify(x => x.UpdateSubsciptionsForPortfolio(It.Is<Guid>(p => p == _portfolioGuid), It.Is<Guid>(u => u == _user.UserId)));
            }

            [Fact]
            public void PortfolioUpdate_Status_To_Private_Updates_Filters_FromScreeningTool()
            {
                //arrange
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared, _user);
                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                //Act
                _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Private, _user);

                //Assert
                _filterMock.Verify(x => x.UpdateFiltersFromScreeningTool(It.Is<Guid>(p => p == _portfolioGuid)
                    , It.Is<Guid>(u => u == _user.UserId)
                    , It.Is<string>(n => n == portfolio.Name))
                    );
            }
        }

        public class AddCompaniesTest
        {
            private readonly IMongoCollection<CorporateData> _corporateDataCollection;
            private readonly ICustomPortfolioUpdateHandler _sut;
            private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioMatches>> _portfolioMatchesRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioUserInput>> _userInputRepositoryMock;
            private readonly Mock<IScreeningToolFilterManager> _filterMock;
            private readonly Mock<ISubscribeToPortfolioManagement> _subscriptionManagement;
            private readonly Guid _portfolioGuid = Guid.NewGuid();
            private readonly Guid _companyId = Guid.NewGuid();
            private readonly Mock<IEsgInputFileRepository> _esgInputFileRepositoryMock;
            private readonly CompanyMatchingLogic _companyMatchingLogic;

            private readonly PortfolioUserClaims _user = new PortfolioUserClaims
            {
                UserName = "ileana.popescu@sustainalytics.com",
                UserFullName = "Ileana Popescu",
                UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f98"),
                AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
            };

            private readonly PortfolioUserClaims _anotherUser = new PortfolioUserClaims
            {
                UserName = "teodor.bajan@sustainalytics.com",
                UserFullName = "Teodor bajan",
                UserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f99"),
                AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98")
            };
            private readonly Dictionary<string, string> _serviceBusParams = new Dictionary<string, string>
            {
                { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
                { "RegionEndpoint", "TT" },
                { "SessionId", "Portfolios" },
                { "TopicPath", "test-topic" },
            };
            private Mock<CorporateDataUniversesLoader> _corporateDataMock;
            
            public AddCompaniesTest()
            {
                _portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();
                _userInputRepositoryMock = new Mock<IRepositoryCollection<PortfolioUserInput>>();
                _filterMock = new Mock<IScreeningToolFilterManager>();
                _subscriptionManagement = new Mock<ISubscribeToPortfolioManagement>();
                _esgInputFileRepositoryMock = new Mock<IEsgInputFileRepository>();
                _sut = new CustomPortfolioUpdateHandler(_portfolioRepositoryMock.Object,
                    _portfolioDetailsRepositoryMock.Object,
                    _portfolioMatchesRepositoryMock.Object,
                    _userInputRepositoryMock.Object,
                    _esgInputFileRepositoryMock.Object, new Replication.Publisher.ServiceBusPublisher( _serviceBusParams),
                    new CompanyMatchingLogic(MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                _sut.SetScreeningToolFilterManagement(_filterMock.Object);
                _sut.SetSubscriptionManager(_subscriptionManagement.Object);
                _sut.SetPortfolioMatching(new PortfolioMatching(new CompanyMatchingLogic(_corporateDataCollection), _corporateDataMock.Object));
                _companyMatchingLogic = new CompanyMatchingLogic(_corporateDataCollection);
            }

            [Fact]
            public void AddCompanyToPortfolio_Throws_Exception_When_Modification_Not_Authorized()
            {
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared,
                  _user);

                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                //Assert
                Assert.Throws<PortfolioModificationUnauthorizedException>(() => _sut.UpdatePortfolioStatus(_portfolioGuid, PortfolioSharingStatus.Private, _anotherUser));
            }

            [Fact]
            public void AddCompanyToPortfolio_When_security_Already_exists_returns_true()
            {
                
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared, _user);

                var companySearch =
                    new Company
                    {
                        CompanyId = 1057062927,
                        CompanyName = "test",
                        MainTicker = "SEA",
                        Country = "Austria",
                        SubPeerGroupId = 25203612,
                    };

                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                _portfolioDetailsRepositoryMock.Setup(
                    repo => repo.ReadCount(It.IsAny<Expression<Func<PortfolioDetails, bool>>>())).Returns(1);

                var expected = _sut.AddCompanyToPortfolio(_portfolioGuid, _companyMatchingLogic.FindGuidForOneCompany(companySearch), _user);
                Assert.True(expected.SecuritiesExists);
            }

            [Fact]
            public void AddCompanyToPortfolio_CompanyCount_Is_Increased_By_1()
            {
                //Arrange
                var portfolioGuid = Guid.NewGuid();
                Portfolio updatedPortfolio = null;

                var companySearch =
                   new Company
                   {
                       CompanyId = 1057062927,
                       CompanyName = "test",
                       MainTicker = "SEA",
                       Country = "Austria",
                       SubPeerGroupId = 25203612,
                   };

                var portfolio = PortfolioBuilder.Build(portfolioGuid, "test", PortfolioSharingStatus.Private, _user);
                portfolio.CompanyCount = 2;
                _portfolioRepositoryMock.Setup(x => x.Read(portfolioGuid)).Returns(portfolio);
                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);

                //Act
                _sut.AddCompanyToPortfolio(portfolioGuid, _companyMatchingLogic.FindGuidForOneCompany(companySearch), _user);

                //Assert
                Assert.Equal(3, updatedPortfolio.CompanyCount);
            }

            [Fact]
            public void AddCompanyToPortfolio_When_Two_Securities_marked_as_main_returns_securities_saved_with_errors_true()
            {
                var portfolio = PortfolioBuilder.Build(_portfolioGuid, "test", PortfolioSharingStatus.Shared,
                 _user);

                var securities = new List<Company>{
                  
                new Company()
                {
                    CompanyId = 1057062927,
                    CompanyName = "test",
                    MainTicker="SEA",
                    Country="Austria",
                    SubPeerGroupId=25203612,
                },
                new Company()
                {
                    CompanyId = 1057062927,
                    CompanyName = "test",
                    MainTicker="SEA",
                    Country="Austria",
                    SubPeerGroupId=25203612,
                }
                    };


                _portfolioRepositoryMock.Setup(x => x.Read(_portfolioGuid)).Returns(portfolio);

                _portfolioDetailsRepositoryMock.Setup(
                    repo => repo.ReadCount(It.IsAny<Expression<Func<PortfolioDetails, bool>>>())).Returns(1);

                var result = _sut.AddCompanyToPortfolio(_portfolioGuid, _companyMatchingLogic.FindGuidForOneCompany(securities[0]), _user);

                Assert.True(result.SavedWithErrors);
            }

            [Fact]
            public void AddCompanyToPortfolio_Replaces_Portfolio_Content()
            {
                //Arrange
                var portfolioGuid = Guid.NewGuid();

                var portfolio = PortfolioBuilder.Build(portfolioGuid, "test", PortfolioSharingStatus.Private, _user);
                _portfolioRepositoryMock
                    .Setup(repo => repo.Read(It.Is<Guid>(x => x == portfolioGuid))).Returns(portfolio);

                _portfolioDetailsRepositoryMock.Verify(x => x.DeleteWhere(It.IsAny<Expression<Func<PortfolioDetails, bool>>>()), Times.AtLeastOnce);
            }

            [Fact]
            public void AddCompaniesToPortfolio_Reset_Company_Count_When_Empty_List()
            {
                //Arrange
                var portfolioGuid = Guid.NewGuid();
                Portfolio updatedPortfolio = null;

                var portfolio = PortfolioBuilder.Build(portfolioGuid, "test", PortfolioSharingStatus.Private, _user);
                portfolio.CompanyCount = 2;
                _portfolioRepositoryMock.Setup(x => x.Read(portfolioGuid)).Returns(portfolio);
                _corporateDataMock.Setup(x => x.GetCompanyUniverses(1008034128)).Returns(new int[] { });

                _portfolioRepositoryMock.Setup(repo => repo.CreateOrUpdate(It.IsAny<Portfolio>())).Callback<Portfolio>(x => updatedPortfolio = x);



                //Assert
                Assert.Equal(0, updatedPortfolio.CompanyCount);
            }
        }

        public class PortfolioAddDetailsTests
        {
            private readonly ICustomPortfolioUpdateHandler _sut;
            private readonly Mock<IRepositoryCollection<Portfolio>> _portfolioRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioDetails>> _portfolioDetailsRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioMatches>> _portfolioMatchesRepositoryMock;
            private readonly Mock<IRepositoryCollection<PortfolioUserInput>> _userInputRepositoryMock;
     
            private readonly Mock<IScreeningToolFilterManager> _filterMock;
            private readonly Mock<ISubscribeToPortfolioManagement> _subscriptionManagement;
            private readonly Mock<IEsgInputFileRepository> _esgInputFileRepositoryMock;

            private readonly IMongoCollection<CorporateData> _corporateDataCollection;

            private readonly Dictionary<string, string> _serviceBusParams = new Dictionary<string, string>
            {
                { "ConnectionString", "Endpoint=sb://sust-test-ns.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Dh/4Cq0qrOC7xOJFUYHLGJvQ6pqj4BuwjTS4HUjL6uQ=" },
                { "RegionEndpoint", "TT" },
                { "SessionId", "Portfolios" },
                { "TopicPath", "test-topic" },
            };
            private readonly Mock<CorporateDataUniversesLoader> _corporateDataMock;

            public PortfolioAddDetailsTests()
            {

                _portfolioRepositoryMock = new Mock<IRepositoryCollection<Portfolio>>();
                _portfolioDetailsRepositoryMock = new Mock<IRepositoryCollection<PortfolioDetails>>();
                _portfolioMatchesRepositoryMock = new Mock<IRepositoryCollection<PortfolioMatches>>();
                _userInputRepositoryMock = new Mock<IRepositoryCollection<PortfolioUserInput>>();
                _filterMock = new Mock<IScreeningToolFilterManager>();
                _subscriptionManagement = new Mock<ISubscribeToPortfolioManagement>();
                _esgInputFileRepositoryMock = new Mock<IEsgInputFileRepository>();
                _sut = new CustomPortfolioUpdateHandler(_portfolioRepositoryMock.Object,
                    _portfolioDetailsRepositoryMock.Object,
                    _portfolioMatchesRepositoryMock.Object,
                    _userInputRepositoryMock.Object,
                    _esgInputFileRepositoryMock.Object, new Replication.Publisher.ServiceBusPublisher( _serviceBusParams),
                    new CompanyMatchingLogic(MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));
                _sut.SetScreeningToolFilterManagement(_filterMock.Object);
                _sut.SetSubscriptionManager(_subscriptionManagement.Object);
                _sut.SetPortfolioMatching(new PortfolioMatching(new CompanyMatchingLogic(_corporateDataCollection), _corporateDataMock.Object));
            }

            [Fact]
            public void AddPortfolioAndDetails_Returns_The_CreatedPortfolio()
            {
                //Arrange
                var portfolioDetails = new List<PortfolioSecuritiesRow>();

                Assert.True(false, "Refactor this test due to modifications");
            }
        }

        public class PortfolioSecuritiesMappingTest
        {
            private readonly IPortfolioDetailsFactory _sut = MainSecurityFactory.GetFactory(new CompanyMatchingLogic(MongoFactory.GetCollectionFromDatabase<CorporateData>(ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString)));

            [Fact]
            public void CompanySearch_To_Security_Mapping()
            {
                var companySearch =
                       new Company
                       {
                           CompanyId = 1057062927,
                           CompanyName = "test",
                           MainTicker = "SEA",
                           Country = "Austria",
                           SubPeerGroupId = 25203612,
                       };

                var result = _sut.CompanySearchToPortfolioDetails(Guid.Parse("b4c7a367-ebd5-4111-b0f2-dbe53849d7d0"),
                    companySearch);
                var expectedResult = new PortfolioDetails
                {
                    CompanyId = Guid.Parse("b4c7a367-ebd5-4111-b0f2-dbe53849d7d0"),
                    CompanyNameLowercase = "test",
                    CompanyNameUrlFriendly = "test",
                    DisplayInfo = new DisplayInformation("123456", string.Empty),
                    Id = Guid.Parse("b4c7a367-ebd5-4111-b0f2-dbe53849d7d0"),
                    MatchedInfo = new MatchedInformation("123456", "test"),
                    SecurityId = "1"
                };

                Assert.Equal(expectedResult.Dump(), result.Dump());
            }
        }
    }
}